package cn.com.bluemoon.daps.sync.core.sync.sql;

import com.alibaba.druid.DbType;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.statement.SQLAlterTableStatement;
import lombok.extern.slf4j.Slf4j;

import javax.validation.constraints.NotNull;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Jarod.Kong
 */
@Slf4j
public final class SqlUtils {
    private SqlUtils() {
    }

    /**
     * 简化ddl多语句
     */
    public static List<String> simplifyDDL(@NotNull String tableName, @NotNull List<String> ddl, DbType dbType, boolean formatSql) {
        try {
            List<SQLStatement> sqlStatements = ddl.stream().flatMap(sql -> SQLUtils.parseStatements(sql, dbType).stream()).collect(Collectors.toList());
            if (sqlStatements.isEmpty()){
                return ddl;
            }
            // 仅对语句都是表结构变更（如：修改表注释的不进行合并）
            boolean allMatch = sqlStatements.stream().allMatch(s -> s instanceof SQLAlterTableStatement && !((SQLAlterTableStatement) s).getItems().isEmpty());
            if (allMatch) {
                String alterTableDdl = String.format("alter table %s ", tableName) + sqlStatements.stream()
                        .filter(sqlStatement -> sqlStatement instanceof SQLAlterTableStatement)
                        .flatMap(s -> ((SQLAlterTableStatement) s).getItems().stream().map(i -> SQLUtils.toSQLString(i, dbType)))
                        .collect(Collectors.joining(", "));
                log.info("简化SQL为：{}", alterTableDdl);
                if (formatSql) {
                    String formatStr = SQLUtils.format(alterTableDdl, dbType);
                    return Collections.singletonList(formatStr);
                } else {
                    return Collections.singletonList(alterTableDdl);
                }
            }
            log.info("源sql非所有为表的字段或索引结构变更，暂不支持合并为一条语句，ddl={}", ddl);
            return sqlStatements.stream().map(i -> SQLUtils.toSQLString(i, dbType)).collect(Collectors.toList());
        } catch (Exception e) {
            log.error("简化SQL，暂不支持解析ddl，返回原值{}", ddl, e);
        }
        return ddl;
    }

    /**
     * 简化ddl多语句
     */
    public static List<String> simplifyDDL(@NotNull String tableName, @NotNull String ddl, DbType dbType) {
        return simplifyDDL(tableName, Collections.singletonList(ddl), dbType, true);
    }

}
